package com.taobao.taokeeper.monitor.core.task.runable;

import com.taobao.taokeeper.common.GlobalInstance;
import com.taobao.taokeeper.common.constant.SystemConstant;
import com.taobao.taokeeper.model.AlarmSettings;
import com.taobao.taokeeper.model.ZooKeeperCluster;
import com.taobao.taokeeper.model.type.Message;
import com.taobao.taokeeper.monitor.core.ThreadPoolManager;
import com.taobao.taokeeper.reporter.alarm.TbMessageSender;
import common.toolkit.java.entity.HostPerformanceEntity;
import common.toolkit.java.exception.SSHException;
import common.toolkit.java.util.StringUtil;
import common.toolkit.java.util.io.SSHUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

import static com.taobao.taokeeper.common.constant.SystemConstant.passwordOfSSH;
import static com.taobao.taokeeper.common.constant.SystemConstant.userNameOfSSH;
import static common.toolkit.java.constant.EmptyObjectConstant.EMPTY_STRING;
import static common.toolkit.java.constant.SymbolConstant.PERCENT;
import static common.toolkit.java.constant.SymbolConstant.SLASH;

/**
 * Description: Collect zooKeeper machine performance CPU/LOAD/MEM
 *
 * @author 银时 yinshi.nc@taobao.com
 * @Date Dec 26, 2011
 */
public class ZKServerPerformanceCollector implements Runnable {

    private static final Logger LOG = LoggerFactory.getLogger(ZKServerPerformanceCollector.class);

    private String ip;
    private AlarmSettings alarmSettings;
    private ZooKeeperCluster zookeeperCluster;

    /**
     * @param ip
     * @param alarmSettings
     * @param zookeeperCluster
     */
    public ZKServerPerformanceCollector(String ip, AlarmSettings alarmSettings, ZooKeeperCluster zookeeperCluster) {
        this.ip = ip;
        this.alarmSettings = alarmSettings;
        this.zookeeperCluster = zookeeperCluster;
    }

    @Override
    public void run() {
        try {
            LOG.warn("{}", SystemConstant.portOfSSH);
            LOG.warn(userNameOfSSH);
            LOG.warn(passwordOfSSH);

            HostPerformanceEntity hostPerformanceEntity = SSHUtil.getHostPerformance(ip, SystemConstant.portOfSSH, userNameOfSSH, passwordOfSSH);
            sendAlarm(alarmSettings, hostPerformanceEntity, zookeeperCluster.getClusterName());
            GlobalInstance.putHostPerformanceEntity(ip, hostPerformanceEntity);
            LOG.info("HostPerformanceEntity collect of #" + zookeeperCluster.getClusterName() + "-" + ip);
        } catch (SSHException e) {
            LOG.warn("HostPerformanceEntity collect of " + ip + " ：" + e.getMessage());
        } catch (Throwable exception) {
            LOG.error("程序出错: " + exception.getMessage());
            exception.printStackTrace();
        }
    }

    /**
     * check if alarm
     */
    public void sendAlarm(AlarmSettings alarmSettings, HostPerformanceEntity hostPerformanceEntity, String clusterName) {

        if (null == alarmSettings)
            return;

        String wangwangList = alarmSettings.getWangwangList();
        String phoneList = alarmSettings.getPhoneList();

        String maxCpuUsage = alarmSettings.getMaxCpuUsage();
        String maxMemoryUsage = alarmSettings.getMaxMemoryUsage();
        String maxLoad = alarmSettings.getMaxLoad();

        String dataDir = alarmSettings.getDataDir();
        String dataLogDir = alarmSettings.getDataLogDir();
        String maxDiskUsage = alarmSettings.getMaxDiskUsage();

        if (!StringUtil.isBlank(maxCpuUsage)) { // Cpu usage alarm
            String cpuUsage = hostPerformanceEntity.getCpuUsage();
            if (!StringUtil.isBlank(cpuUsage) && cpuUsage.endsWith("%")) {
                cpuUsage = cpuUsage.replaceAll("%", "");
                double difference = Double.parseDouble(cpuUsage) - Double.parseDouble(maxCpuUsage);
                if (0 < difference) {
                    LOG.warn("ZK Server " + hostPerformanceEntity.getIp() + " cpu Usage too high：" + cpuUsage + "-" + maxCpuUsage + "=" + difference);
                    // Alarm
                    if (GlobalInstance.needAlarm.get()) {
                        ThreadPoolManager.addJobToMessageSendExecutor(new TbMessageSender(
                                new Message(wangwangList, "ZK Server cpu usage too high-" + clusterName, hostPerformanceEntity.getIp() + " cpu usage too high! " + cpuUsage + "-" + maxCpuUsage + "=" + difference,
                                        Message.MessageType.WANGWANG),
                                new Message(phoneList, "ZK Server cpu usage too high-" + clusterName, "ZK Server cpu usage too high-" + clusterName + hostPerformanceEntity.getIp() + " cpu usage too high! " + cpuUsage + "-"
                                        + maxCpuUsage + "=" + difference, Message.MessageType.SMS)
                        ));
                        LOG.info("WangWangList: " + wangwangList);
                    }
                }
            }
        }

        if (!StringUtil.isBlank(maxMemoryUsage)) { // Memory usage alarm
            String memoryUsage = hostPerformanceEntity.getMemoryUsage();
            if (!StringUtil.isBlank(memoryUsage) && memoryUsage.endsWith("%")) {
                memoryUsage = memoryUsage.replaceAll("%", "");
                double difference = Double.parseDouble(memoryUsage) - Double.parseDouble(maxMemoryUsage);
                if (0 < difference) {
                    LOG.warn("ZK Server " + hostPerformanceEntity.getIp() + " memory usage too high: " + memoryUsage + "-" + maxMemoryUsage + "=" + difference);
                    // Alarm
                    if (GlobalInstance.needAlarm.get()) {
                        ThreadPoolManager.addJobToMessageSendExecutor(new TbMessageSender(

                                new Message(wangwangList, "ZK Server memory usage too high:-" + clusterName, hostPerformanceEntity.getIp() + " memory too high：" + memoryUsage + "-" + maxMemoryUsage + "=" + difference,
                                        Message.MessageType.WANGWANG),

                                new Message(phoneList, "", "ZK Server memory usage too high-" + clusterName + hostPerformanceEntity.getIp() + memoryUsage + "-" + maxMemoryUsage + "=" + difference, Message.MessageType.SMS)

                        ));
                        LOG.info("WangWangList: " + wangwangList);
                    }
                }
            }
        }

        if (!StringUtil.isBlank(maxLoad)) { // Load usage alarm
            String load = hostPerformanceEntity.getLoad();
            if (!StringUtil.isBlank(load)) {
                double difference = Double.parseDouble(load) - Double.parseDouble(maxLoad);
                if (0 < difference) {
                    LOG.warn("ZK Server " + hostPerformanceEntity.getIp() + " load usage too high: " + load + "-" + maxLoad + "=" + difference);
                    if (GlobalInstance.needAlarm.get()) {

                        ThreadPoolManager.addJobToMessageSendExecutor(new TbMessageSender(

                                new Message(wangwangList, " ZK Server load usage too high-"
                                        + clusterName, hostPerformanceEntity.getIp() + "：" + load + "-" + maxLoad + "=" + difference,
                                        Message.MessageType.WANGWANG),

                                new Message(phoneList, "", "ZK Server load usage too high-" + clusterName + hostPerformanceEntity.getIp() + "：" + load + "-"
                                        + maxLoad + "=" + difference, Message.MessageType.SMS)

                        ));
                        LOG.info("WangWangList: " + wangwangList);
                    }
                }
            }
        }

        try {
            if (!StringUtil.isBlank(dataDir) || !StringUtil.isBlank(dataLogDir)) { // 需要进行
                // disk容量
                // 报警

                dataDir = StringUtil.trimToEmpty(dataDir);
                dataLogDir = StringUtil.trimToEmpty(dataLogDir);

                if (!StringUtil.isBlank(maxDiskUsage)) {

                    Map<String, String> diskUsageMap = hostPerformanceEntity.getDiskUsageMap();
                    if (null != diskUsageMap) {
                        for (String mountedOn : diskUsageMap.keySet()) {

                            if (StringUtil.trimToEmpty(mountedOn).equalsIgnoreCase(SLASH))
                                continue;

                            if (dataDir.startsWith(StringUtil.trimToEmpty(mountedOn))
                                    || dataLogDir.startsWith(StringUtil.trimToEmpty(mountedOn))) {
                                int diskUsage = Integer.parseInt(StringUtil.trimToEmpty(diskUsageMap.get(mountedOn)).replace(PERCENT,
                                        EMPTY_STRING));
                                if (diskUsage > Integer.parseInt(maxDiskUsage)) {
                                    LOG.warn("ZK Server " + hostPerformanceEntity.getIp() + " disk usage too high, " + mountedOn + ": " + diskUsage
                                            + "%, max setting usage is: " + maxDiskUsage + "%");
                                    if (GlobalInstance.needAlarm.get()) {
                                        ThreadPoolManager.addJobToMessageSendExecutor(new TbMessageSender(

                                                new Message(wangwangList,
                                                        "ZK Server disk usage too high-" + clusterName, hostPerformanceEntity.getIp() + " disk usage too high, "
                                                        + mountedOn + ":" + diskUsage + "%, max setting usage is: " + maxDiskUsage + "%",
                                                        Message.MessageType.WANGWANG),

                                                new Message(phoneList, "", "ZK disk usage too high-" + clusterName
                                                        + hostPerformanceEntity.getIp() + "," + mountedOn + ": " + diskUsage
                                                        + "%, max setting usage is: " + maxDiskUsage + "%", Message.MessageType.SMS)
                                        ));
                                        LOG.info("WangWangList: " + wangwangList);
                                    }
                                }
                            }
                        }
                    }
                }

            }
        } catch (Throwable e) {
            LOG.error("Error when ckeck disk usage：" + e.getMessage());
            e.printStackTrace();
        }// disk alarm

    }

}
